using System.Collections.Generic;
using System.IO;
using System.Reflection;
using NUnit.Framework;
using Com.ContentRendering.Api.LoaderEngine;
using Com.ContentRendering.Api.LoaderEngine.Exceptions;

namespace Com.ContentRendering.Api.LoaderEngineComponentTest
{
    [TestFixture]
    public class ComponentTest
    {
        /// <summary/>
        internal class PreprocessingSeparatorsContext : PreprocessingSeparatorsInterface
        {
            /// <summary/>
            public string ImportStart
            {
                get { return "<+>"; }
            }

            /// <summary/>
            public string ImportEnd
            {
                get { return "</+>"; }
            }

            /// <summary/>
            public string GetSetConstantStart
            {
                get { return  "<=>"; }
            }

            /// <summary/>
            public string GetSetConstantEnd
            {
                get { return "</=>"; }
            }

            /// <summary/>
            public string GetSetConstantCenter
            {
                get { return "="; }
            }

            /// <summary/>
            public string GetSetFlagStart
            {
                get { return "<|>"; }
            }

            /// <summary/>
            public string GetSetFlagEnd
            {
                get { return "</|>"; }
            }

            /// <summary/>
            public string GetSetFlagCenter
            {
                get { return "|"; }
            }
        }

        private Dictionary<string, string> _resources;
        private DocumentLoader _documentLoader;

        private string LoadTemplate(string name)
        {
            string typeFullName = string.Format(
                "Com.ContentRendering.Api.LoaderEngineComponentTest.Test.Input.{0}.tem",
                name);

            return this._resources[typeFullName];
        }

        [TestFixtureSetUp]
        public void SetUpFixture()
        {
            this._resources = new Dictionary<string, string>();

            Assembly assembly = Assembly.GetExecutingAssembly();

            foreach (string typeFullName in assembly.GetManifestResourceNames())
            {
                using (Stream stream = assembly.GetManifestResourceStream(typeFullName))
                {
                    using (TextReader textReader = new StreamReader(stream))
                    {
                        this._resources.Add(typeFullName, textReader.ReadToEnd());
                    }
                }
            }
        }

        [SetUp]
        public void SetUp()
        {
            this._documentLoader = new DocumentLoader(
                this.LoadTemplate,
                new PreprocessingSeparatorsContext());
        }

        [Test]
        public void NoLinksTest()
        {
            string output = this._documentLoader.Load("NoLinks");

            Assert.AreEqual(
                this._resources["Com.ContentRendering.Api.LoaderEngineComponentTest.Test.Output.NoLinks.txt"], 
                output);
        }

        [Test]
        public void OneLinkTest()
        {
            string output = this._documentLoader.Load("OneLink");

            Assert.AreEqual(
                this._resources["Com.ContentRendering.Api.LoaderEngineComponentTest.Test.Output.OneLink.txt"],
                output);
        }

        [Test]
        public void ConstantTest()
        {
            string output = this._documentLoader.Load("Constant");

            Assert.AreEqual(
                this._resources["Com.ContentRendering.Api.LoaderEngineComponentTest.Test.Output.Constant.txt"],
                output);
        }

        [Test]
        public void FlagTest()
        {
            string output = this._documentLoader.Load("Flag");

            Assert.AreEqual(
                this._resources["Com.ContentRendering.Api.LoaderEngineComponentTest.Test.Output.Flag.txt"],
                output);
        }

        [Test]
        public void ConstantLinkTest()
        {
            string output = this._documentLoader.Load("ConstantLink");

            Assert.AreEqual(
                this._resources["Com.ContentRendering.Api.LoaderEngineComponentTest.Test.Output.ConstantLink.txt"],
                output);
        }

        [Test]
        public void ConstanDoubleLinkTest()
        {
            string output = this._documentLoader.Load("ConstantDoubleLink");

            Assert.AreEqual(
                this._resources["Com.ContentRendering.Api.LoaderEngineComponentTest.Test.Output.ConstantDoubleLink.txt"],
                output);
        }

        [Test]
        public void ConstantInFlagTest()
        {
            string output = this._documentLoader.Load("ConstantInFlag");

            Assert.AreEqual(
                this._resources["Com.ContentRendering.Api.LoaderEngineComponentTest.Test.Output.ConstantInFlag.txt"],
                output);
        }

        [Test]
        public void FlagInConstantTest()
        {
            string output = this._documentLoader.Load("FlagInConstant");

            Assert.AreEqual(
                this._resources["Com.ContentRendering.Api.LoaderEngineComponentTest.Test.Output.FlagInConstant.txt"],
                output);
        }

        [Test]
        public void ImportStartSeparatorMissingTest()
        {
            try
            {
                this._documentLoader.Load("ImportStartSeparatorMissing");
            }
            catch (ImportStartSeparatorMissingException)
            {
                return;
            }

            Assert.Fail();
        }

        [Test]
        public void ImportNameMissingTest()
        {
            try
            {
                this._documentLoader.Load("ImportNameMissing");
            }
            catch (ImportNameMissingException)
            {
                return;
            }

            Assert.Fail();
        }

        [Test]
        public void ImportEndSeparatorMissingTest()
        {
            try
            {
                this._documentLoader.Load("ImportEndSeparatorMissing");
            }
            catch (ImportEndSeparatorMissingException)
            {
                return;
            }

            Assert.Fail();
        }

        [Test]
        public void ConstantStartSeparatorMissingTest()
        {
            try
            {
                this._documentLoader.Load("ConstantStartSeparatorMissing");
            }
            catch (ConstantStartSeparatorMissingException)
            {
                return;
            }

            Assert.Fail();
        }

        [Test]
        public void ConstantNameMissingTest()
        {
            try
            {
                this._documentLoader.Load("ConstantNameMissing");
            }
            catch (ConstantNameMissingException)
            {
                return;
            }

            Assert.Fail();
        }

        [Test]
        public void ConstantEndSeparatorMissingTest()
        {
            try
            {
                this._documentLoader.Load("ConstantEndSeparatorMissing");
            }
            catch (ConstantEndSeparatorMissingException)
            {
                return;
            }

            Assert.Fail();
        }

        [Test]
        public void FlagStartSeparatorMissingTest()
        {
            try
            {
                this._documentLoader.Load("FlagStartSeparatorMissing");
            }
            catch (FlagStartSeparatorMissingException)
            {
                return;
            }

            Assert.Fail();
        }

        [Test]
        public void FlagNameMissingTest()
        {
            try
            {
                this._documentLoader.Load("FlagNameMissing");
            }
            catch (FlagNameMissingException)
            {
                return;
            }

            Assert.Fail();
        }

        [Test]
        public void FlagEndSeparatorMissingTest()
        {
            try
            {
                this._documentLoader.Load("FlagEndSeparatorMissing");
            }
            catch (FlagEndSeparatorMissingException)
            {
                return;
            }

            Assert.Fail();
        }

        [Test]
        public void CircularReferenceTest()
        {
            try
            {
                this._documentLoader.Load("CircularReference");
            }
            catch (CircularReferenceException)
            {
                return;
            }

            Assert.Fail();
        }
    }
}
